package com.wwu.system.common.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wwu.common.constant.SecurityConst;
import com.wwu.common.utils.DateUtils;
import com.wwu.common.utils.SpringUtils;
import com.wwu.common.web.ResultObj;
import com.wwu.system.entity.LoginLog;
import com.wwu.system.service.ILoginLogService;
import org.springframework.security.authentication.*;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;

/**
 * 登陆失败处理器
 * @author 一蓑烟雨
 * @version 1.0.0
 * @date 2023-06-01 19:04
 */
@Component
public class SecurityLoginFailedHandler extends SimpleUrlAuthenticationFailureHandler {
    @Resource
    private ILoginLogService loginLogService;

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException{
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        PrintWriter out = response.getWriter();
        ResultObj bean = null;
        if (exception instanceof UsernameNotFoundException) {
            bean = ResultObj.except("用户名不存在");
        } else if (exception instanceof BadCredentialsException) {
            bean = ResultObj.except("密码不正确");
        } else if (exception instanceof DisabledException) {
            bean = ResultObj.except("用户已被禁用");
        } else if (exception instanceof LockedException) {
            bean = ResultObj.except("账户已被锁定");
        } else if (exception instanceof CredentialsExpiredException) {
            bean = ResultObj.except("证书已过期");
        } else if (exception instanceof SessionAuthenticationException) {
            bean = ResultObj.except("账号已在其他地方登陆，不允许重复登陆");
        } else if (exception instanceof InsufficientAuthenticationException) {
            bean = ResultObj.except(exception.getMessage());
        } else {
            bean = ResultObj.except(SecurityConst.LOGIN_FAILURE);
        }
        //记录登陆异常日志
        String userName = request.getParameter("username");
        if(StringUtils.hasText(userName)){
            asyncLoginLogFailedHandler(request,response,bean.getMsg());
        }

        out.write(new ObjectMapper().writeValueAsString(bean));
        out.flush();
        out.close();
    }

    /**
     * 组织异步记录登陆日志实体
     * @param request
     * @param response
     * @param msg
     * @author 一蓑烟雨
     * @date 2023/7/29 16:29
     */
    private void asyncLoginLogFailedHandler(HttpServletRequest request, HttpServletResponse response, String msg){
        LoginLog loginLog = new LoginLog();
        String userName = request.getParameter("username");
        loginLog.setUserName(userName);
        loginLog.setSessionId(userName+" | "+DateUtils.convertDateTimeToStrUk(new Date()));
        loginLog.setUserName(userName);
        loginLog.setNickName("未知");
        loginLog.setLoginIp(SpringUtils.getIpAddress(request));
        loginLog.setLoginRemoteHost(SpringUtils.getRemoteHost(request));
        loginLog.setLoginStatus(1);
        HashMap<String, String> hashMap = SpringUtils.getBrowserAndOsInfo(request);
        loginLog.setLoginDesc(msg);
        loginLog.setBrowser(hashMap.get("browserName"));
        loginLog.setOs(hashMap.get("osName"));
        loginLog.setLoginTime(LocalDateTime.now());

        //调用异步方法
        loginLogService.saveLoginLog(loginLog);
    }
}